package cc.autoapi.pucong.auto.flow.core.flow.execNode.task.system;


import cc.autoapi.pucong.auto.flow.core.flow.execNode.entity.node.ExecNode;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.entity.node.ExecParamIn;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.exception.AutoDesignException;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.utils.JythonUtils;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.entity.node.NodeParamIn;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.entity.node.NodeParamOut;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.selfenum.DataTypeEnum;
import cc.autoapi.pucong.auto.flow.core.flow.execNode.task.AbstractTask;
import org.apache.commons.lang3.StringUtils;
import org.python.core.PyDictionary;
import org.python.core.PyFunction;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.util.PythonInterpreter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PythonScriptTask extends AbstractTask {

    private List<NodeParamIn> paramsIns;
    private List<NodeParamOut> paramsOuts;

    public PythonScriptTask() {
        paramsIns = new ArrayList<>();

        paramsOuts = new ArrayList<>();
    }

    @Override
    public void run() {
        String content = getExecNode().getNodeScript();
        if (StringUtils.isBlank(content)) {
            throw new AutoDesignException("脚本内容不能为空！,节点名称：" + getExecNode().getNodeName());
        }
        // 执行脚本
        ExecNode execNode = getExecNode();
        List<ExecParamIn> paramInList = execNode.getParamInList();
        Map<PyObject, PyObject> mapObjectParams = new HashMap<>(16);
        for (ExecParamIn paramIn : paramInList) {
            DataTypeEnum dateType = paramIn.getDateType();
            PyObject pyObject = JythonUtils.toPyObject(dateType, paramIn.getDateValue().toString());
            mapObjectParams.put(new PyString(paramIn.getParamCode()), pyObject);
        }
        mapObjectParams.put(new PyString("nodeId"), new PyString("nodeId"));
        mapObjectParams.put(new PyString("instanceNodeId"), new PyString("instanceNodeId"));
        mapObjectParams.put(new PyString("nodeName"), new PyString("nodeName"));
        mapObjectParams.put(new PyString("context"), null);
        String python2 = "def run (params) {\n" + content + "\n}";
        // 执行
        PyObject pyobj = null;
        try (PythonInterpreter interpreter = new PythonInterpreter()) {
            interpreter.exec(python2);

            // 第一个参数为期望获得的函数（变量）的名字，第二个参数为期望返回的对象类型
            PyFunction pyFunction = interpreter.get("run", PyFunction.class);
            //调用函数，如果函数需要参数，在Java中必须先将参数转化为对应的“Python类型”
            pyobj = pyFunction.__call__(new PyDictionary(mapObjectParams));
        }

        Object json = JythonUtils.toObjectFromPyObject(pyobj);
        setParamOutValue("result", json);
    }

    @Override
    public String getTaskName() {
        return "python脚本节点";
    }

    @Override
    public String getTaskDesc() {
        return "本组件可以把脚本内容设置到“script”属性。\n" +
                "本组件只能用来做数据处理，无法实现复杂的业务功能。脚本内容需要存在 def run(params)方法，且组件会执行脚本的run函数，把脚本的输出对象，作为组件的输出参数。\n" +
                "生成的Python脚本，脚本内容尽量不要超过20行，该脚本包含一个名为def run(params)的函数。参数params是一个JSON对象，函数应返回一个JSON对象作为输出。确保代码简洁且高效。\n" +
                "脚本示例：\n" +
                "def run(params)\n" +
                "    return {\n" +
                "        context.a\n" +
                "    }";
    }

    @Override
    public Boolean getTaskParamInAuto() {
        return true;
    }

    @Override
    public String getTaskSvgIcon() {
        return "<svg t=\"1728283580804\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"4285\" width=\"32\" height=\"32\"><path d=\"M366.635375 495.627875c8.93024999-1.488375 17.8605-2.480625 26.79075-2.48062499h-7.44187499 241.61287499c10.418625 0 20.341125-1.488375 30.26362501-3.969 44.65124999-12.403125 77.3955-52.093125 77.3955-101.20950002V185.053625c0-57.5505-49.116375-101.2095-107.65912501-110.63587501-37.209375-5.9535-91.287-8.93024999-128.00025-8.93024999-36.71325001 0-71.938125 3.472875-103.194 8.93024999C305.115875 90.29374999 288.74374999 123.534125 288.74374999 185.053625v66.48075h223.25625001V288.74374999H216.3095C133.456625 288.74374999 65.983625 387.96874999 65.4875 510.0155v1.9845c0 22.325625 1.9845 43.659 6.449625 63.504C90.29374999 667.78325001 147.84424999 735.25625001 216.3095 735.25625001h35.224875v-106.66687501c0-62.51174999 46.63574999-120.558375 115.101-132.9615z m23.814-283.7835c-22.325625 0-40.68225001-18.356625-40.18612499-40.68225 0-22.325625 17.8605-40.68225001 40.18612499-40.68225s40.68225001 18.356625 40.68225 40.68225c-0.496125 22.82175001-18.356625 40.68225001-40.68225 40.68225z\" fill=\"#0075AA\" p-id=\"4286\"></path><path d=\"M949.086125 434.108375C927.75275001 349.271 872.682875 288.74374999 807.6905 288.74374999h-35.224875v94.75987501c0 78.883875-51.597 135.93825001-115.101 145.86075-6.449625 0.99224999-12.89925001 1.488375-19.34887499 1.48837501H396.402875c-10.418625 0-20.341125 1.488375-30.26362499 3.969-44.65124999 11.907-77.3955 48.62025001-77.3955 96.74437499V834.48125001c0 57.5505 58.046625 91.783125 115.10099998 108.15524999 67.969125 19.845 142.387875 23.317875 224.24850002 0 54.077625-15.379875 107.163-46.63574999 107.16299998-108.15525001v-61.5195h-223.25624999V735.25625001h295.6905c58.54275001 0 109.643625-49.6125 134.449875-122.04675001 10.418625-30.263625 16.372125-64.49625001 16.372125-101.2095 0-27.286875-3.472875-53.5815-9.426375-77.891625z m-316.52775 372.58987501c22.325625 0 40.186125 18.356625 40.186125 40.68224999 0 22.325625-18.356625 40.68225001-40.186125 40.68225001-22.325625 0-40.68225001-18.356625-40.68225-40.68225001 0.496125-22.325625 18.356625-40.68225001 40.68225-40.68225001z\" fill=\"#FFD400\" p-id=\"4287\"></path></svg>";
    }

    @Override
    public List<NodeParamIn> getPropertyParamsIns() {
        return paramsIns;
    }

    @Override
    public List<NodeParamOut> getPropertyParamsOuts() {
        return paramsOuts;
    }
}
